package slap;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import slap.annotation.Scan;

import jodd.io.findfile.FilepathScanner;
import jodd.util.ReflectUtil;

public class Resources {
	
	private static final Logger logger = LoggerFactory.getLogger(Resources.class);
	
	public static class Presets {
		
		public static class Names{
			public static final String DIR_NAME_CLASSES = "classes";
			public static final String DIR_NAME_STATIC = "static";
			public static final String DIR_NAME_ETC = "etc";
		}
		
		public static final String DIR_CLASSES = Slap.class.getClassLoader()
				.getResource("").getPath();

		public static final String DIR_HOME = DIR_CLASSES.substring(0, DIR_CLASSES.length() - 
				Names.DIR_NAME_CLASSES.length()-1);

		public static final String DIR_ETC = DIR_HOME + Names.DIR_NAME_ETC+"/";

		public static final String DIR_STATIC = DIR_HOME + Names.DIR_NAME_STATIC+"/";
		
	}
	
	public static void init() {
		FilepathScanner classesScanner = new FilepathScanner(){
			@Override
			protected void onFile(File file) {
				if(file.getName().endsWith(".class")){
					ManagedClasses.scanClass(file);
				}
			}
		};
		classesScanner.includeDirs(true).includeFiles(true).recursive(true).scan(Presets.DIR_CLASSES);
	}
	
	public static class ManagedMethods{
		
		private static Map<Class<? extends Annotation>, List<Method>> methods = new HashMap<Class<? extends Annotation>, List<Method>>();
		
		public static void scanMethods(Class<?> clazz) {
			for(Method method : ReflectUtil.getAccessibleMethods(clazz)){
				Annotation[] ans = method.getAnnotations();
				for(Annotation an : ans){
					List<Method> ams = methods.get(an.annotationType());
					if(ams == null){
						ams = new ArrayList<Method>();
					}
					ams.add(method);
					methods.put(an.annotationType(), ams);
				}
			}
		}
		
		public static List<Method> withAnnotation(Class<? extends Annotation> anClass){
			return methods.get(anClass);
		}

		public static void cleanup() {
			methods = null;
		}
		
	}
	
	public static class ManagedClasses {
		
		private static Map<Class<?>, Object> instancesPool = new HashMap<Class<?>, Object>();
		
		public static Class<?>[] withAnnotation(){
			return null;
		}
		
		public static Class<?> [] all(){
			return null;
		}
		
		public static <T> T instanceOf(Class<? extends T> clazz){
			return null;
		}
		
		protected static void scanClass(File file) {
			String abs = file.getAbsolutePath();
			String className = abs.substring(Presets.DIR_CLASSES.length()-1, abs.length()-6);
			className = className.replace(File.separatorChar, '.');
			if(className.charAt(className.length()-2) == '$' && Character.isDigit(className.charAt(className.length()-1))){
				return;
			}
			Class<?> clazz = null;
			try {
				clazz = Class.forName(className);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
				return;
			}
			
			Scan scan = clazz.getAnnotation(Scan.class);
			if(scan != null){
				ManagedMethods.scanMethods(clazz);
			}
			
		}
		
	}
	

}
